package org.base.common.util;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.base.common.exception.BusinessException;
import org.base.common.exception.ExceptionEnum;
import org.base.common.token.JWTToken;
import org.springframework.util.ReflectionUtils;

import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class TokenUtils {

    /**
     * 私钥
     */
    private final static String PRIVATE_KEY = "dudu";

    private final static SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

    private final static Key signingKey = new SecretKeySpec(Base64.decodeBase64(PRIVATE_KEY), signatureAlgorithm.getJcaName());

    public static String getToken(JWTToken token) {
        final long timeMillis = System.currentTimeMillis();
        final long exp = token.getExpMin();
        Map<String, Object> claims = new HashMap<>();
        claims.put(Claims.ISSUED_AT, new Date());
        JwtBuilder jwtBuilder = Jwts.builder()
                .setExpiration(new Date(timeMillis + exp * 60 * 1000))
                .setClaims(claims);
        jwtBuilder.signWith(signatureAlgorithm, signingKey);
        ReflectionUtils.doWithFields(JWTToken.class, (field) -> {
            field.setAccessible(true);
            final String name = field.getName();
            final Object value = field.get(token);
            claims.put(name, value);
        });
        return jwtBuilder.compact();
    }

    /**
     * token校验
     *
     * @param token
     * @return
     */
    public static void isValid(String token) {
        try {
            Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token.trim());
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
            BusinessException.throwEx(ExceptionEnum.EXPIRED_TOKEN);
        }
    }

    public static JWTToken parseToken(String token) {
        Claims claims = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token.trim()).getBody();
        final JSONObject jsonObject = JSONUtil.parseObj(claims);
        return jsonObject.toBean(JWTToken.class);
    }

}